/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package cz.worktracker.controller;

import cz.worktracker.enums.DataSetsEnum;
import cz.worktracker.model.entities.Taskinterval;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import javax.annotation.ManagedBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.inject.Inject;
import javax.inject.Named;
import org.hibernate.Criteria;

import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;


/**
 * TaskManager
 * Vytvoření nového projektu
 * @since 2010-04-23
 * @author kyjovsky
 */

@ManagedBean
@SessionScoped
@Named
public class TaskintervalManager extends AbstractManager
                            implements Serializable {

        private static final long serialVersionUID = 1L;


        private Taskinterval taskinterval;

        /* TABULKA */
        private AbstractPaginator paginator;
        private DataModel dataModel;
        private DataSetsEnum DSEnum;
        private int rowsPerPage = DSEnum.ITEMS_PER_PAGE_DEFAULT.getValue();

        private String sortByField = DSEnum.SORT_BY_FIELD.getStringValue();
        private String sortDirection = DSEnum.SORT_DIRECTION.getStringValue();
        /* TABULKA */

        private ArrayList<Taskinterval> taskIntervalList;


        @Inject UserManager userManager;
        @Inject TaskManager taskManager;

        @PostConstruct
        public void construct() {
            init();
        }

        @PreDestroy
        public void destroy() {
            taskinterval = null;
            paginator = null;
            dataModel = null;
        }


        private void init() {
            if( taskinterval == null ) {
                taskIntervalList = new ArrayList<Taskinterval>();
                taskinterval = new Taskinterval();
                taskinterval.setIdTask(-1);
            }
        }


        public Taskinterval getTaskinterval() {
            return taskinterval;
        }

        public void setTaskinterval(Taskinterval taskinterval) {
            this.taskinterval = taskinterval;
        }


        /**
         * Method nulls reference of dataModel.
        */
        private void resetDataModel() {
            dataModel = null;
        }


        /**
        * Method nulls reference of paginator.
        */
        public void resetPagination() {
            paginator = null;
        }

        /**
        * Returns page switcher and override abstract methods from AbstractPaginator.
        * @return Paginator object.
        */
        public AbstractPaginator getPaginator() {
            if( paginator == null ) {
                paginator = new AbstractPaginator( rowsPerPage ) {

               /*
                * While creating a new instance we have to implement abstract
                * methods defined in AbstractPaginator class.
                */

                @Override
                public int getItemsCount() {
                    return getTaskintervalsCount();
                }

                @Override
                public DataModel createPageDataModel() {
                    ListDataModel list = null;

                    try {
                        Transaction tx = getSession().beginTransaction();
                        Criteria ct = getSession().createCriteria(Taskinterval.class);
                        ct.add( Restrictions.eq( "idTask", taskManager.getTask().getId() ) );
                        /* TODO nefunguje :-( 
                        if( getSortDirection().equalsIgnoreCase( "asc" ) ) {
                            ct.addOrder( Order.asc( getSortByField()) );
                        } else {
                            ct.addOrder( Order.desc( getSortByField()) );
                        }
                        */

                        ct.addOrder( Order.desc("startTime") );
                        ct.setFirstResult(getPageFirstItem());
                        ct.setMaxResults(getPageSize());

                        list = new ListDataModel(ct.list());
                        tx.commit();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    return list;
                    }
                };
            }
            return paginator;
        }


       /**
        * Returns count of records returned to view.
        * @return int
        */
        public int getRowsPerPage() {
            return rowsPerPage;
        }


        /**
         * Sets count of records returned to view.
         * @param rowsPerPage
         */
        public void setRowsPerPage( int rowsPerPage ) {
            this.rowsPerPage = rowsPerPage;

            resetDataModel();
            resetPagination();
        }

        /**
         * Returns DataModel for dataTable.
         * @return DataModel for dataTable.
        */
        public DataModel getList() {
            if( dataModel == null ) {
                dataModel = getPaginator().createPageDataModel();
            }

            return dataModel;
        }


        /**
        * Next page.
        */
        public void next() {
            System.out.println(">> last >> " + getPaginator().getActualPage());
            getPaginator().nextPage();
            System.out.println(">> last 2 >> " + getPaginator().getActualPage());
            resetDataModel();
        }

        /**
        * Last page.
        */
        public void last() {
            getPaginator().lastPage();
            resetDataModel();
        }


        /**
        * Previous page.
        */
        public void previous() {
            System.out.println(">> prev >> " + getPaginator().getActualPage());
            getPaginator().previousPage();
            System.out.println(">> prev 2 >> " + getPaginator().getActualPage());
            resetDataModel();
        }

        /**
        * First page.
        */
        public void first() {
            getPaginator().firstPage();
            resetDataModel();
        }


        /**
        * Increments count of items per page.
        */
        public void more() {
            setRowsPerPage(getRowsPerPage() + DSEnum.ITEMS_PER_PAGE_INCREMENT.getValue());

            resetPagination();
            resetDataModel();
        }


        /**
        * * Decrements count of items per page.
        */
        public void less() {
            setRowsPerPage(getRowsPerPage() - DSEnum.ITEMS_PER_PAGE_INCREMENT.getValue());

            resetPagination();
            resetDataModel();
        }


        /**
        * Retrieves sort params through context and initiates sort.
        */
        public void sort() {
            /**
            * Try to gain params send by <f:param />
            */
            FacesContext context = FacesContext.getCurrentInstance();
            Map requestMap = context.getExternalContext().getRequestParameterMap();
            setSortByField( (String) requestMap.get("by") );
            setSortDirection( (String) requestMap.get("order") );

            resetPagination();
            resetDataModel();

        }


        /**
        * Returns projects count.
        * @return int means projects count.
        */
        public int getTaskintervalsCount() {
            Transaction tx = getSession().beginTransaction();
            String hql = "select count(*) from Taskinterval as taskinterval where taskinterval.idTask = '" + taskManager.getTask().getId() + "'";
            int count = ( (Long) (getSession().createQuery(hql).iterate().next()) ).intValue();
            tx.commit();
            return count;
        }


        /**
        * Returns field name in JPA entity according which sorting will be provided.
        * @return String
        */
        public String getSortByField() {
            return sortByField;
        }


        /**
        * Sets field name in JPA entity according which sorting will be provided.
        * @param sortByField
        */
        public void setSortByField(String sortByField) {
            this.sortByField = sortByField;
        }


        /**
        * Returns sort direction (ascending: asc; descending desc).
        * @return String
        */
        public String getSortDirection() {
            return sortDirection;
        }


        /**
        * Sets sort direction (ascending: asc; descending desc).
        * @param sortDirection
        */
        public void setSortDirection(String sortDirection) {
            this.sortDirection = sortDirection;
        }


        public String getTotalTime() {

       int id_task = taskManager.getTask().getId();

       resetDataModel();
       ListDataModel list = null;

       try {
           Transaction tx = getSession().beginTransaction();
           Criteria ct = getSession().createCriteria(Taskinterval.class);
           ct.add( Restrictions.eq( "idTask", id_task ) );

           list = new ListDataModel(ct.list());
           tx.commit();
       } catch (Exception e) {
           e.printStackTrace();
       }

       Taskinterval tmp_interval;
       long diff = 0;

       for (int i = 0; i < list.getRowCount(); i++) {
           list.setRowIndex(i);
           tmp_interval = (Taskinterval) list.getRowData();
           if (tmp_interval.getStopTime() == null) {
              diff += (new Date()).getTime() - tmp_interval.getStartTime().getTime();
           }
           else {
              diff += tmp_interval.getStopTime().getTime() - tmp_interval.getStartTime().getTime();
           }

        }


        return getStringTime(new Date(diff - 3600000));


    }

    public String getStringTime (Date date) {
      String hours = ((Integer) date.getHours()).toString();
      String minutes;
      String seconds;

      if (date.getMinutes() < 10) minutes = "0" + ((Integer) date.getMinutes()).toString();
      else minutes = ((Integer) date.getMinutes()).toString();

      if (date.getSeconds() < 10) seconds = "0" + ((Integer) date.getSeconds()).toString();
      else seconds = ((Integer) date.getSeconds()).toString();

      return hours + ":" + minutes + ":" + seconds;
    }


    public String getIntervalLength() {

        int id_interval = ((Taskinterval) getList().getRowData()).getId();

        Taskinterval tmp_interval = new Taskinterval();


        try {
            Transaction tx = getSession().beginTransaction();
            Criteria ct = getSession().createCriteria(Taskinterval.class);
            ct.add( Restrictions.eq( "id", id_interval ) );

            tmp_interval = (Taskinterval) ct.list().get(0);
            tx.commit();

        } catch (Exception e) {
           e.printStackTrace();
        }

        if(tmp_interval.getId() == null) return "- null -";

        if (tmp_interval.getStopTime() == null) {
            return "> "  + getStringTime(new Date((new Date().getTime()) - tmp_interval.getStartTime().getTime() - 3600000));
        }
        else {
            return getStringTime(new Date(tmp_interval.getStopTime().getTime() - tmp_interval.getStartTime().getTime() - 3600000));
        }

    }


    public String getLastWork() {
       Taskinterval newInterval;
       try {
          Transaction tx = getSession().beginTransaction();
          Criteria ct = getSession().createCriteria(Taskinterval.class);
          ct.add( Restrictions.eq( "idTask", taskManager.getTask().getId() ) );
          ct.addOrder( Order.desc("stopTime") );
          int size =  ct.list().size();
          if (size <= 0) return null;
          newInterval = (Taskinterval) ct.list().get(size-1);
          if (newInterval.getStopTime() == null) {
                tx.commit();
                return getStringDate(new Date());
          }
          newInterval = (Taskinterval) ct.list().get(0);
          tx.commit();
       } catch (Exception e) {
          e.printStackTrace();
          return null;
       }

       if(newInterval.getId() == null) return "- null -";

       return getStringDate(newInterval.getStopTime());
    }


    public String getStringDate(Date date) {
      String day = ((Integer) date.getDate()).toString();
      String month = ((Integer) (date.getMonth()+1)).toString();
      String year = ((Integer) (date.getYear() + 1900)).toString();
      String hours;
      String minutes;
      if (date.getHours() < 10) hours = "0" + ((Integer) date.getHours()).toString();
      else hours = ((Integer) date.getHours()).toString();

      if (date.getMinutes() < 10) minutes = "0" + ((Integer) date.getMinutes()).toString();
      else minutes = ((Integer) date.getMinutes()).toString();

      return day + "." + month + "." + year + " - " + hours + ":" + minutes;
    }


    public String getFirstWork() {
       Taskinterval newInterval;
       try {
          Transaction tx = getSession().beginTransaction();
          Criteria ct = getSession().createCriteria(Taskinterval.class);
          ct.add( Restrictions.eq( "idTask", taskManager.getTask().getId() ) );
          ct.addOrder( Order.asc("startTime") );
          if (ct.list().size() <= 0) return null;
          newInterval = (Taskinterval) ct.list().get(0);
          tx.commit();
       } catch (Exception e) {
          e.printStackTrace();
          return null;
       }

       if(newInterval.getId() == null) return "- null -";

       return getStringDate(newInterval.getStartTime());
    }


    public String getStartTimeString() {

        int id_interval = ((Taskinterval) getList().getRowData()).getId();

        Taskinterval tmp_interval = new Taskinterval();

        try {
            Transaction tx = getSession().beginTransaction();
            Criteria ct = getSession().createCriteria(Taskinterval.class);
            ct.add( Restrictions.eq( "id", id_interval ) );
            tmp_interval = (Taskinterval) ct.list().get(0);
            tx.commit();

        } catch (Exception e) {
           e.printStackTrace();
        }

        if(tmp_interval.getId() == null) return "- null -";

        return getStringDate(tmp_interval.getStartTime());

    }

    public String getStopTimeString() {

        int id_interval = ((Taskinterval) getList().getRowData()).getId();

        Taskinterval tmp_interval = new Taskinterval();

        try {
            Transaction tx = getSession().beginTransaction();
            Criteria ct = getSession().createCriteria(Taskinterval.class);
            ct.add( Restrictions.eq( "id", id_interval ) );

            tmp_interval = (Taskinterval) ct.list().get(0);
            tx.commit();

        } catch (Exception e) {
           e.printStackTrace();
        }

        if(tmp_interval.getId() == null) return "- null -";

        if (tmp_interval.getStopTime() == null) {
            return "- RUN -";
        }
        else {
            return getStringDate(tmp_interval.getStopTime());
        }

    }

    public void remove () {
        int id_interval = ((Taskinterval) getList().getRowData()).getId();

        Taskinterval tmp_interval = new Taskinterval();

        try {
            Transaction tx = getSession().beginTransaction();
            Criteria ct = getSession().createCriteria(Taskinterval.class);
            ct.add( Restrictions.eq( "id", id_interval ) );

            tmp_interval = (Taskinterval) ct.list().get(0);

            getSession().delete(tmp_interval);
            
            tx.commit();

        } catch (Exception e) {
           e.printStackTrace();
        }

        resetDataModel();

    }


    /**
     * Returns recent tasksinterval.
     * @return
     */
    public ArrayList<Taskinterval> getRecentTasks() {
        ArrayList<Integer> taskIds = taskManager.getTaskIds();

        if( taskIntervalList == null ) {
            taskIntervalList = new ArrayList<Taskinterval>();
        }

        try {
            Transaction tx = getSession().beginTransaction();
            Criteria ct = getSession().createCriteria( Taskinterval.class );

            /*
            ct.setProjection( Projections.projectionList()
                    .add( Projections.groupProperty("idTask") ) );*/
            ct.add( Restrictions.in( "idTask", taskIds.toArray() ) );
            ct.addOrder( Order.desc("stopTime") );
            ct.addOrder( Order.desc("startTime") );

            ct.setMaxResults( DSEnum.ITEMS_MAX_RECENT_TIMERS.getValue() );
            Iterator it = ct.list().iterator();

            getTaskIntervalList().clear();
            int i = 0;
            while( it.hasNext() ) {
               // Taskinterval tmpTaskInt = (Taskinterval) it.next();
                getTaskIntervalList().add( (Taskinterval) it.next() );
                System.out.println( it.next() );
            }

            tx.commit();
            
        } catch (Exception e) {
            e.printStackTrace();
        }

        return getTaskIntervalList();
    }


    /**
     * Returns tasks interval
     * @return
     */
    public ArrayList<Taskinterval> getTaskIntervalList() {
        return taskIntervalList;
    }


    /**
     * Sets tasks interval
     * @param taskIntervalList
     */
    public void setTaskIntervalList(ArrayList<Taskinterval> taskIntervalList) {
        this.taskIntervalList = taskIntervalList;
    }
    



}
